package com.allinfinance.starters.loader;

import com.allinfinance.starters.exception.LoadResourceException;
import com.allinfinance.starters.interfaces.StringConfigLoader;
import com.allinfinance.starters.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @desc: 数据库配置加载器
 * @author: wujp
 * @create: 2025-01-14 16:30
 */
public class DbConfigLoader implements StringConfigLoader {
    private Logger logger = LoggerFactory.getLogger(DbConfigLoader.class);

    private DataSource dataSource;
    private String configTableName;
    private String configKeyFieldName;
    private String configValueFieldName;

    @Override
    public Map<String, String> load() {
        Map<String, String> configMap = new ConcurrentHashMap<>();
        logger.info("DbConfigLoader load config start.");
        try {
            Connection connection = dataSource.getConnection();
            PreparedStatement ps = connection.prepareStatement(getConfigQuerySql());
            ResultSet resultSet = ps.executeQuery();
            while (resultSet.next()) {
                String key = resultSet.getString(this.configKeyFieldName);
                String value = resultSet.getString(this.configValueFieldName);
                if (StringUtil.isBank(key) || StringUtil.isBank(value)) {
                    logger.warn("config_key={} or config_value={} is empty skip load this config", key, value);
                    continue;
                }
                configMap.put(key, value.trim());
            }
        } catch (SQLException e) {
            throw new LoadResourceException("DbConfigLoader load config resource error", e);
        }
        logger.info("DbConfigLoader load config end. config size is {}", configMap.size());
        return configMap;
    }

    private String getConfigQuerySql() {
        StringBuffer sb = new StringBuffer();
        sb.append("select ")
                .append(this.configKeyFieldName)
                .append(",")
                .append(this.configValueFieldName)
                .append(" ")
                .append("from ")
                .append(this.configTableName);
        logger.info("DbConfigLoader query db config sql = [{}] ",sb.toString());
        return sb.toString();
    }

    @Override
    public int getOrder() {
        return Integer.MAX_VALUE;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(this.dataSource, "dataSource must not be null");
        Assert.notNull(this.configTableName, "configTableName must not be null");
        Assert.notNull(this.configKeyFieldName, "configKeyFieldName must not be null");
        Assert.notNull(this.configValueFieldName, "configValueFieldName must not be null");
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public String getConfigTableName() {
        return configTableName;
    }

    public void setConfigTableName(String configTableName) {
        this.configTableName = configTableName;
    }

    public String getConfigKeyFieldName() {
        return configKeyFieldName;
    }

    public void setConfigKeyFieldName(String configKeyFieldName) {
        this.configKeyFieldName = configKeyFieldName;
    }

    public String getConfigValueFieldName() {
        return configValueFieldName;
    }

    public void setConfigValueFieldName(String configValueFieldName) {
        this.configValueFieldName = configValueFieldName;
    }

}
